<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <button>点击</button>
    <button>点击</button>
    <button>点击</button>
    <script>
        //                  三种不同情况下的处理函数内部this指向的方法 : bind(),call(),apply() 
        // 1.call() 
        // (1)参数说明:(要把调用call的函数内的this修改为谁,参数,参数...)
        // (2)调用函数 可以改变调用call的函数内的 this指向
        // var o = {
        //     name: 'andy'
        // }
        // function fn(x, y) {
        //     console.log(this);
        //     console.log(x + y);
        // }
        // fn()//window
        // fn.call()//window
        // fn.call(o, 1, 2)//o
        // function Father(name, age, sex) {
        //     this.name = name
        //     this.age = age
        //     this.sex = sex
        // }
        // function Son(x,y,z) {
        //     // 修改为谁(要指向的对象),调用call的函数内的this就指向谁(要指向的对象)
        //     Father.call(this,x,y,z)
        // }
        // var son = new Son('刘德华', 18, '男')
        // var fh = new Father('张学友',20,'女')
        // console.log(fh.name);
        // console.log(fh.age);
        // console.log(fh.sex);

        // console.log(son.name); 
        // console.log(son.age);  
        // console.log(son.sex);  


        // 2.apply()应用运用的意思
        // (1)参数说明:(要把调用apply的函数内的this修改为谁,[参数,参数...])
        // (2)也是调用函数 也可以改变调用apply的函数内的 this指向
        // (3)但是它的参数必须是数组(伪数组)的形式传递
        // (4)apply主要运行场景 可以利用数组的特性做相应操作 例如借助数学内置对象Math求数组内最大/小值
        // var o = {
        //     name: 'andy'
        // }
        // function fn() {
        //     console.log(this);
        //     console.log(arr);// [123]/'[pink]'
        // }
        // // fn.apply(o)
        // // fn.apply(o,1,2)//报错 传递参数必须是数组形式
        // var arr = [1, 2, 3, 99]
        // // var arr = ['pink']
        // fn.apply(o, arr)

        // var max = Math.max.apply(Math, arr)//最大值
        // var min = Math.min.apply(Math, arr)//最小值
        // console.log(max, min);


        //3.bind() 绑定 捆绑的意思 
        //(1)参数说明:(要把调用bind的函数内的this修改为谁,参数,参数...)
        //(2) 不会调用原来的函数 但同样会改变原来函数内部的this 指向
        //(3)返回的是 改变原函数this指向后 产生的新函数 需变量接收
        //(4)主要使用场景:如果有的函数不需要被立即调用 但是有需要改变调用bind的函数内的this指向 此时用bind 例如:当我们点击了按钮 就禁用这个按钮 三秒之后开启这个按钮
        var o = {
            name: 'andy'
        }
        function fn(a, b) {
            console.log(this);
            console.log(a + b);
        }

        var f = fn.bind(o, 3, 5)
        f()
        // 示例:
        // var btn = document.querySelector('button')
        // btn.onclick = function () {
        //     this.disabled = true
        //     setTimeout(function () {
        //         // 首先定时器里的this指向的是调用定时器的顶级对象window,而window是没有disabled属性的 所以不会执行
        //         this.disabled = false//此时this就指向的btn了(下面已经通过bind修改了) 所以就有disabled属性了
        //         //此时bind括号里的this 是在定时器外面就不会指向window了 但因为还在按钮点击事件里面 所以当前this指向的会是触发点击事件的按钮 
        //     }.bind(this), 2000)
        // }


        // 多个按钮情况下:
        var btns = document.querySelectorAll('button')
        for (var i = 0; i < btns.length; i++) {
            btns[i].onclick = function () {
                this.disabled = true
                setTimeout(function () {
                    this.disabled = false
                }.bind(this), 2000)
            }
        }
  // 总结一句话 那个函数调用了bind就意味着调用者内部的this可以被修改指向 这取决于bind的第一个参数
    </script>
</body>

</html>